import { Notify } from "quasar";
import { useAPIStore } from "stores/api";
import { ref } from "vue";

export default function () {
  let ws = null;
  let rec;
  const rosClient = {
    connected: ref(false), // 连接状态
    robotPose: ref({}), // 设备实时位置
    scanPose: ref([]), // 激光雷达数据
    loadMapData: ref(function (data) {}), // 设备建图
    rawImg: ref(""),
    isCalibration: ref(false), // 是否标定中
    calibrationData: ref({
      flag: 1,
    }),
    loadCamera: ref(function (data) {}), // 相机预览
  };
  /**
   * 创建ws连接
   */
  rosClient.createWs = () => {
    ws = new WebSocket(useAPIStore().rosUrl);
    if (ws) {
      ws.onmessage = (e) => {
        wsOnMessage(e);
      };
      ws.onopen = () => {
        rosClient.connected = true;
        heartCheck.start();
        Notify.create({ type: "positive", message: "已建立与ROS的直连" });
      };
      ws.onclose = () => {
        rosClient.connected = false;
      };
      ws.onerror = () => {
        rosClient.connected = false;
        rosClient.reConnect();
      };
    }
  };

  /**
   * 设置心跳
   */
  const heartCheck = {
    timeoutObj: null,
    start: () => {
      heartCheck.timeoutObj = setTimeout(function () {
        if (rosClient.connected) ws.send("heartbeat");
        else rosClient.reConnect();
      }, 10000);
    },
    reset: () => {
      clearTimeout(heartCheck.timeoutObj);
      heartCheck.start();
    },
  };

  /**
   * 重连机制
   */
  rosClient.reConnect = () => {
    console.log("尝试重连");
    if (rosClient.connected) return;
    rec && clearTimeout(rec);
    rec = setTimeout(rosClient.createWs, 5000);
  };

  /**
   * ws接收消息
   */
  function wsOnMessage(e) {
    heartCheck.reset();
    const resData = JSON.parse(e.data);
    switch (resData.op.valueOf()) {
      case "publish":
        processTopic(resData);
        break;
    }
  }

  /**
   * 处理topic收到的消息
   */
  function processTopic(rosObject) {
    switch (rosObject.topic) {
      case "/robot_pose":
        rosClient.robotPose.value = rosObject.msg;
        break;
      case "/map_metadata":
        rosClient.loadMapData.value(rosObject.msg);
        break;
      case "/status_calib":
        rosClient.isCalibration.value = rosObject.msg.data;
        break;
      case "/raw_img":
        rosClient.rawImg.value = rosObject.msg;
        break;
      case "/calibrate_state":
        rosClient.calibrationData.value = rosObject.msg;
        console.log(rosObject.msg);
        break;
      case "/scan_simplified":
        rosClient.scanPose.value =
          rosObject.msg.polygon !== undefined
            ? rosObject.msg.polygon.points !== undefined
              ? rosObject.msg.polygon.points
              : []
            : [];
        break;
    }
  }

  /**
   * ws发送消息
   * @param object
   */
  rosClient.wsSend = (object) => {
    if (ws.readyState === 1) {
      ws.send(JSON.stringify(object));
    } else {
      if (rosClient.connected) {
        setTimeout(() => rosClient.wsSend(object), 200);
      }
    }
  };

  /**
   * 断开ws
   */
  rosClient.closeWs = () => {
    ws.close();
  };

  rosClient.subscribe = (topic) => {
    rosClient.wsSend({ op: "subscribe", topic });
  };
  rosClient.unsubscribe = (topic) => {
    rosClient.wsSend({ op: "unsubscribe", topic });
  };
  rosClient.publish = (topic, msg) => {
    rosClient.wsSend({ op: "publish", topic, msg });
  };

  return rosClient;
}
